/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2020年3月20日
 * <修改描述:>
 */
package com.tx.component.file.resource;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;

import com.tx.component.file.exception.FileContextResourceException;
import com.tx.component.file.util.FileContextUtils;

/** 
 * 对文件容器资源的描述<br/>
 * <功能详细描述>
 * 
 * @author  Administrator
 * @version  [版本号, 2020年3月20日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public abstract class AbstractFCResource implements FCResource {
    
    /** The default buffer size for {@link #write(OutputStream)} */
    protected static final int WRITE_BUFFER_SIZE = 4096;
    
    /** 文件目录 */
    protected String catalog;
    
    /** 文件所在目录的相对路径 */
    protected String relativePath;
    
    /** 文件类型 */
    protected FCResourceTypeEnum type;
    
    /** <默认构造函数> */
    public AbstractFCResource() {
        super();
    }
    
    /** <默认构造函数> */
    public AbstractFCResource(String catalog) {
        super();
        this.catalog = catalog;
    }
    
    /**
     * @param 对catalog进行赋值
     */
    protected void setCatalog(String catalog) {
        this.catalog = catalog;
    }
    
    /**
     * @param 对relativePath进行赋值
     */
    protected void setRelativePath(String relativePath) {
        relativePath = FileContextUtils.handleRelativePath(relativePath);
        this.relativePath = relativePath;
    }
    
    /**
     * @param 对type进行赋值
     */
    protected void setType(FCResourceTypeEnum type) {
        this.type = type;
    }
    
    /**
     * @return 返回 catalog
     */
    @Override
    public String getCatalog() {
        return catalog;
    }
    
    /**
     * @return
     */
    @Override
    public String getRelativePath() {
        return this.relativePath;
    }
    
    /**
     * 返回FCResource的type
     * <功能详细描述>
     * @return
     * @throws IOException [参数说明]
     * 
     * @return FCResourceTypeEnum [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    protected FCResourceTypeEnum doGetType() {
        return null;
    }
    
    /**
     * @return 返回 type
     */
    @Override
    public FCResourceTypeEnum getType() throws FileContextResourceException {
        if (type == null) {
            if (!this.exists()) {
                //如果不存在，则类型返回为null
                return null;
            }
            this.type = doGetType();
        }
        return type;
    }
    
    /**
     * @param filter
     * @param depthwise
     * @return
     * @throws IOException
     */
    @Override
    public List<FCResource> findFiles(FCResourceFilter fileFilter,
            boolean depthwise) throws FileContextResourceException {
        List<FCResource> resList = new ArrayList<>();
        nestedFindFiles(Arrays.asList(this), resList, fileFilter, depthwise);
        return resList;
    }
    
    /**
     * 默认的hashCode方法<br/>
     * @return
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((catalog == null) ? 0 : catalog.hashCode());
        result = prime * result
                + ((relativePath == null) ? 0 : relativePath.hashCode());
        return result;
    }
    
    /**
     * 默认的equals方法<br/>
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        AbstractFCResource other = (AbstractFCResource) obj;
        if (!org.apache.commons.lang3.StringUtils.equalsIgnoreCase(catalog,
                other.catalog)) {
            return false;
        }
        if (!org.apache.commons.lang3.StringUtils.equalsIgnoreCase(relativePath,
                other.relativePath)) {
            return false;
        }
        return true;
    }
    
    /**
     * 迭代查询子级文件夹<br/>
     * <功能详细描述>
     * @param parents
     * @param selected
     * @param filter
     * @throws IOException [参数说明]
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    private static void nestedFindFiles(List<FCResource> parents,
            List<FCResource> selected, FCResourceFilter fileFilter,
            boolean depthwise) throws FileContextResourceException {
        if (CollectionUtils.isEmpty(parents)) {
            return;
        }
        
        List<FCResource> newParents = new ArrayList<>();
        for (FCResource parentTemp : parents) {
            List<FCResource> ps = parentTemp.getChildren();
            if (CollectionUtils.isEmpty(ps)) {
                continue;
            }
            for (FCResource fcrTemp : ps) {
                if (selected.contains(fcrTemp)) {
                    continue;
                }
                
                if (fcrTemp.isFile()) {
                    if (fileFilter != null) {
                        if (fileFilter.accept(fcrTemp)) {
                            selected.add(fcrTemp);
                        }
                    } else {
                        selected.add(fcrTemp);
                    }
                }
                if (fcrTemp.isFolder()) {
                    //如果不含  
                    newParents.add(fcrTemp);
                    //返回的资源信息中是否包含目录资源
                    //selected.add(fcrTemp);
                }
            }
        }
        //迭代查询文件
        if (depthwise && !CollectionUtils.isEmpty(newParents)) {
            nestedFindFiles(newParents, selected, fileFilter, depthwise);
        }
    }
}
